package com.learn.grpc.net;

import cn.hutool.core.thread.ThreadUtil;
import com.learn.grpc.grpc.HelloServiceGrpc;
import com.learn.grpc.grpc.NetServiceGrpc;
import com.learn.grpc.hello.PingRequest;
import com.learn.grpc.hello.PingResponse;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

@Slf4j
public class NetServiceGrpcClient {

    @Test
    public void unaryMethod() {
        //1.构建网络通道
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9091)
                .usePlaintext()
                .build();

        //2.构建客户端
        NetServiceGrpc.NetServiceBlockingStub stub = NetServiceGrpc.newBlockingStub(managedChannel);

        //3.发送多次请求
        for (int i = 0; i < 5; i++) {
            PingRequest request = PingRequest.newBuilder()
                    .setContent("zhangsan_" + i)
                    .build();
            PingResponse resp = stub.normalMethod(request);

            log.info("code:{}, message:{}, data:{}", resp.getCode(), resp.getMessage(), resp.getData());
        }
    }

    @Test
    public void streamServer() {
        //1.构建网络通道
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9091)
                .usePlaintext()
                .build();

        //2.构建客户端
        NetServiceGrpc.NetServiceStub stub = NetServiceGrpc.newStub(managedChannel);

        //3.发送多次请求
        PingRequest request = PingRequest.newBuilder()
                .setContent("请求数据" )
                .build();

        stub.serverStreamMethod(request, new StreamObserver<PingResponse>() {
            @Override
            public void onNext(PingResponse value) {
                // 监听服务器端的 onNext() 写入方法
                log.info("接收到消息:" , value.getData());
            }

            @Override
            public void onError(Throwable t) {
                log.error("发生异常", t);
            }

            @Override
            public void onCompleted() {
                log.info("消息接收完成");
            }
        });

        // 流式API 为异步模式，单测中需要线程等待，否则就直接结束了
        ThreadUtil.sleep(10000);
    }

    @Test
    public void clientStream() {

        //1.构建网络通道
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9091)
                .usePlaintext()
                .build();

        //2.构建客户端
        NetServiceGrpc.NetServiceStub stub = NetServiceGrpc.newStub(managedChannel);

        StreamObserver<PingRequest> requestObserver = stub.clientStreamMethod(new StreamObserver<PingResponse>() {
            @Override
            public void onNext(PingResponse value) {

            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onCompleted() {

            }
        });

        //3.发送多次请求
        for (int i = 0; i < 5; i++) {
            PingRequest request = PingRequest.newBuilder()
                    .setContent("zhangsan_" + i)
                    .build();
            requestObserver.onNext(request);
        }
        // 通知服务端，客户端数据已发送完。否则服务端会一直阻塞等待
        requestObserver.onCompleted();

        // 流式API 为异步模式，单测中需要线程等待，否则就直接结束了
        ThreadUtil.sleep(10000);
    }

    @Test
    public void doubleStream() {

        //1.构建网络通道
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost", 9091)
                .usePlaintext()
                .build();

        //2.构建客户端
        NetServiceGrpc.NetServiceStub stub = NetServiceGrpc.newStub(managedChannel);

        StreamObserver<PingRequest> requestObserver = stub.doubleStreamMethod(new StreamObserver<PingResponse>() {

            private String batchNo = null;
            @Override
            public void onNext(PingResponse value) {
                batchNo = value.getMessage();


                log.info("接收到服务端响应, batchNo:{}, 响应内容:{}", value.getMessage(), value.getData());
            }

            @Override
            public void onError(Throwable t) {
                log.info("服务端响应出错误, batchNo:{}, errorReason:{}", batchNo, t.getMessage());
            }

            @Override
            public void onCompleted() {
                log.info("服务端响应结束, batchNo:{}", batchNo);
            }
        });

        //3.发送多次请求
        for (int i = 0; i < 5; i++) {
            PingRequest request = PingRequest.newBuilder()
                    .setContent("zhangsan_" + i)
                    .build();
            requestObserver.onNext(request);
        }
        // 通知服务器，客户端数据已发送完毕
        requestObserver.onCompleted();

        // 流式API 为异步模式，单测中需要线程等待，否则就直接结束了
        ThreadUtil.sleep(10000);
    }

}
